package button

import (
	"github.com/templui/templui/internal/utils"
	"strings"
)

type Variant string
type Size string
type Type string

const (
	VariantDefault     Variant = "default"
	VariantDestructive Variant = "destructive"
	VariantOutline     Variant = "outline"
	VariantSecondary   Variant = "secondary"
	VariantGhost       Variant = "ghost"
	VariantLink        Variant = "link"
)

const (
	TypeButton Type = "button"
	TypeReset  Type = "reset"
	TypeSubmit Type = "submit"
)

const (
	SizeDefault Size = "default"
	SizeSm      Size = "sm"
	SizeLg      Size = "lg"
	SizeIcon    Size = "icon"
)

type Props struct {
	ID         string
	Class      string
	Attributes templ.Attributes
	Variant    Variant
	Size       Size
	FullWidth  bool
	Href       string
	Target     string
	Disabled   bool
	Type       Type
	Form       string
}

templ Button(props ...Props) {
	{{ var p Props }}
	if len(props) > 0 {
		{{ p = props[0] }}
	}
	if p.Type == "" {
		{{ p.Type = TypeButton }}
	}
	if p.Href != "" && !p.Disabled {
		<a
			if p.ID != "" {
				id={ p.ID }
			}
			href={ templ.SafeURL(p.Href) }
			if p.Target != "" {
				target={ p.Target }
			}
			class={
				utils.TwMerge(
					"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all",
					"disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0",
					"outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
					"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
					"cursor-pointer",
					p.variantClasses(),
					p.sizeClasses(),
					p.modifierClasses(),
					p.Class,
				),
			}
			{ p.Attributes... }
		>
			{ children... }
		</a>
	} else {
		<button
			if p.ID != "" {
				id={ p.ID }
			}
			class={
				utils.TwMerge(
					"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all",
					"disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0",
					"outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
					"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
					"cursor-pointer",
					p.variantClasses(),
					p.sizeClasses(),
					p.modifierClasses(),
					p.Class,
				),
			}
			if p.Type != "" {
				type={ string(p.Type) }
			}
			if p.Form != "" {
				form={ p.Form }
			}
			disabled?={ p.Disabled }
			{ p.Attributes... }
		>
			{ children... }
		</button>
	}
}

func (b Props) variantClasses() string {
	switch b.Variant {
	case VariantDestructive:
		return "bg-destructive text-destructive-foreground shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60"
	case VariantOutline:
		return "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50"
	case VariantSecondary:
		return "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80"
	case VariantGhost:
		return "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50"
	case VariantLink:
		return "text-primary underline-offset-4 hover:underline"
	default:
		return "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90"
	}
}

func (b Props) sizeClasses() string {
	switch b.Size {
	case SizeSm:
		return "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5"
	case SizeLg:
		return "h-10 rounded-md px-6 has-[>svg]:px-4"
	case SizeIcon:
		return "size-9"
	default: // SizeDefault
		return "h-9 px-4 py-2 has-[>svg]:px-3"
	}
}

func (b Props) modifierClasses() string {
	classes := []string{}
	if b.FullWidth {
		classes = append(classes, "w-full")
	}
	return strings.Join(classes, " ")
}
